package unei.net.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by sunlei on 2015/9/1.
 */
public class BasicNioServer {
    private static Selector selector;

    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress("localhost",1024));
        serverSocketChannel.configureBlocking(false);

        selector=Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while(true){
            int cnt=selector.select(10);
            if(cnt==0){
                continue;
            }

            Set<SelectionKey> keys=selector.selectedKeys();
            Iterator<SelectionKey> it=keys.iterator();
            while(it.hasNext()){
                SelectionKey selectionkey=it.next();
                it.remove();
                if(selectionkey.isValid()){
                    selectionkey.interestOps(0);
                }

                if(selectionkey.isAcceptable()){
                    handleAccept(selectionkey);
                }else if(selectionkey.isReadable()){
                    handleRead(selectionkey);
                }else if(selectionkey.isWritable()){
//                    handleWrite(selectionkey,"gogo");
                }
            }
        }
    }

    public static void handleAccept(SelectionKey selectionKey) throws Exception{
        ServerSocketChannel serverSocketChannel= (ServerSocketChannel) selectionKey.channel();
        SocketChannel socketChannel=serverSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        selectionKey.selector().wakeup();
    }

    public static void handleRead(SelectionKey selectionKey) throws Exception{
        ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
        Charset charset=Charset.forName("UTF-8");
        SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
        String content="";
        while(true){
            byteBuffer.clear();
            int len=socketChannel.read(byteBuffer);
            if(len==-1){
                selector.close();
                break;
            }

            if(len==0){
                break;
            }

            byteBuffer.flip();
            content+=charset.decode(byteBuffer).toString();
        }

        System.out.println("receive:"+content);

        ByteBuffer outBuffer = ByteBuffer.wrap(("gogo"+System.lineSeparator()).getBytes());
        socketChannel.write(outBuffer);
    }

    public static void handleWrite(SelectionKey selectionKey,String response) throws Exception{
        ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
        byteBuffer.put(response.getBytes());
        SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
        socketChannel.write(byteBuffer);
        selectionKey.selector().wakeup();
    }
}
